package person.twj.jwt;

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;

@Slf4j
public class TestMain {
    public static void main(String[] args) {
        String username = "admin";
        String password = "123456";

        // 1. SecurityContextHolder    创建身份A
        SecurityContext context = SecurityContextHolder.createEmptyContext();
        Authentication anAuthentication = new UsernamePasswordAuthenticationToken(
                username,
                password);
        context.setAuthentication(anAuthentication);
        SecurityContextHolder.setContext(context);

        // 2. ProviderManager implements AuthenticationManager 验证身份
        // 2.1、创建身份适配器
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider(NoOpPasswordEncoder.getInstance());
        provider.setUserDetailsService(new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                // 从数据库获取用户和密码信息
                if("admin".equals(username)){
                    return User.builder().username("admin").password("123456").build();
                }else{
                    throw new UsernameNotFoundException("用户不存在");
                }
            }
        });
        // 2.2、加入身份provider 到 身份管理器里
        ProviderManager providerManager = new ProviderManager(provider);//provider 可以多个，这里是一个适配器模式，不同的身份验证信息类型（Authentication）需要不同的适配器
        try {
            // 2.3、验证身份
            Authentication authentication = providerManager.authenticate(// 验证身份
                    SecurityContextHolder.getContext().getAuthentication()// 验证身份A是否与我们数据库里的一样
            );
            // 2.4、最后，如果上面的适配器都处理完，还是返回null，则表示验证失败
            if (authentication == null) {
                log.info("验证失败");
                return;
            }
            log.info("身份验证成功");

        }catch (AuthenticationException ae){ // 捕捉认证错误信息
            if(ae.getClass().isAssignableFrom(BadCredentialsException.class)){
                log.error("用户名或密码错误");
            }else if(ae.getClass().isAssignableFrom(CredentialsExpiredException.class)){
                log.error("凭证已过期");
            }else{
                log.error("未知错误 ",ae);
            }
        }
    }

}


